package com.yb.xczx.cloud.auth.provider;

import com.yb.core.enums.LoginTypeEnum;
import com.yb.xczx.cache.manager.api.XczxCacheManager;
import com.yb.xczx.cloud.auth.bean.XczxAbstractAuthenticationToken;
import com.yb.xczx.cloud.auth.bean.XczxSysUser;
import com.yb.xczx.cloud.auth.bean.XczxUserPassAuthenticationToken;
import com.yb.xczx.cloud.auth.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * Copyright (C), 2022-2023, 姚兵
 * Author: 32210
 * Date: 2023/5/17 21:02
 * FileName: XczxTokenAuthenticationProvider
 * Description:
 */
public class XczxUserPassAuthenticationProvider extends XczxAbstractUserDetailsAuthenticationProvider {



    @Autowired
    XczxCacheManager<String,Object> xczxCacheManager;

    @Autowired
    PasswordEncoder passwordEncoder;
    private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();

    public XczxUserPassAuthenticationProvider(){

    }


    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, XczxAbstractAuthenticationToken authentication) throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            this.logger.debug("Failed to authenticate since no credentials provided");
            throw new BadCredentialsException(this.messages
                    .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
        String presentedPassword = authentication.getCredentials().toString();
        if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
            this.logger.debug("Failed to authenticate since password does not match stored value");
            throw new BadCredentialsException(this.messages
                    .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
    }

    @Override
    protected UserDetails retrieveUser(String username, XczxAbstractAuthenticationToken authentication) throws AuthenticationException {

        UserDetails userDetails = this.sysUserService.loadUserByUsername(username);

        return userDetails;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return XczxUserPassAuthenticationToken.class.isAssignableFrom(authentication);
    }

    @Override
    protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
         XczxUserPassAuthenticationToken result = XczxUserPassAuthenticationToken.authenticated((XczxSysUser) user,this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
        result.setDetails(authentication.getDetails());
        ((XczxSysUser) user).setLoginType(LoginTypeEnum.USER_PASS.getLoginType());
        this.logger.debug("Authenticated user");
        return result;
    }
}
